package cn.b504.qpcr.impls;

import azure2java.qpcradapter.QpcrUtils;
import azure2java.qpcradapter.adapter.ConnectedDeviceAdapter;
import azure2java.qpcradapter.adapter.ConnectedDeviceDictionary;
import azure2java.qpcradapter.adapter.DeviceInfoAdapter;
import azure2java.qpcradapter.adapter.entity.*;
import cn.b504.qpcr.entity.*;
import cn.b504.qpcr.entity.data.PcrData;
import cn.b504.qpcr.entity.data.QuantificationData;
import cn.b504.qpcr.exception.DeviceConnectException;
import cn.b504.qpcr.exception.DeviceNotFoundException;
import cn.b504.qpcr.exception.DeviceUnregisterException;
import cn.b504.qpcr.interfaces.Access;
import cn.b504.qpcr.interfaces.Device;
import cn.b504.qpcr.utils.ConstantUtils;
import com.csvreader.CsvReader;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Service
public class DeviceImpl implements Device {
  private final QpcrUtils qpcr;
  private DeviceInfoAdapter[] connections;
  private final Access access;

  public DeviceImpl(QpcrUtils qpcr, Access access) {
    this.qpcr = qpcr;
    this.access = access;
  }

  @Override
  public AjaxResult search() {
    List<DeviceInfo> deviceInfos = new ArrayList<>();
    Map<String, String> id_connectPort = new HashMap<>();
    connections = qpcr.connections();

    File dir;
    try {
      dir = new File(ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX), "coefficients");
    } catch (FileNotFoundException e) {
      return AjaxResult.error(ErrorCode.DIRECTORY_NOT_FOUND, "系统错误：项目文件夹未找到");
    }

    for (DeviceInfoAdapter connection : connections) {
      String id = connection.getId();
      String connectPort = connection.getConnectPort();

      // 防止相同 id、connectPort 的信息重复生成结果
      if (!id_connectPort.containsKey(id) || !connectPort.equals(id_connectPort.get(id))) {
        id_connectPort.put(id, connectPort);

        List<Coefficient> coefficients = new ArrayList<>();
        if (dir.exists() && dir.isDirectory()) {
          File file = new File(dir, id);

          if (file.exists()) {
            CsvReader csvReader = null;
            try {
              csvReader = new CsvReader(file.getAbsolutePath(), ',', StandardCharsets.UTF_8);
              while (csvReader.readRecord()) {
                if (csvReader.getColumnCount() != 7) {
                  continue;
                }
                Double[] arr = new Double[6];
                short channelIndex = -1;
                for (short i = 0; i < 6; i++) {
                  double value = Double.parseDouble(csvReader.get(i + 1));
                  arr[i] = value;
                  if (value == 1) {
                    channelIndex = i;
                  }
                }
                Coefficient coefficient = new Coefficient();
                coefficient.setName(csvReader.get(0));
                coefficient.setChannel(channelIndex);
                coefficient.setCoefficient(arr);
                coefficients.add(coefficient);
              }
            } catch (IOException e) {
              return AjaxResult.error(ErrorCode.CSV_IO_EXCEPTION, "Csv 解析校准系数文件错误");
            } catch (NumberFormatException e) {
              return AjaxResult.error(ErrorCode.DOUBLE_VALUE_OF_EXCEPTION, "解析校准系数转换成 Double 数据类型错误");
            } finally {
              if (csvReader != null) {
                csvReader.close();  // 关闭 CsvReader 对象
              }
            }
          }
        }
        deviceInfos.add(
            new DeviceInfo(
                connectPort,
                id,
                connection.getName(),
                connection.getProductName(),
                connection.getHardwareVersion(),
                connection.getConnectStatus(),
                coefficients
            )
        );
      }
    }
    return AjaxResult.ok(deviceInfos);
  }

  @Override
  public void disconnect(String connectPort) {
    for (ConnectedDeviceDictionary connectedDevice : qpcr.getConnectedDevices()) {
      if (connectedDevice.getKey().getConnectPort().equals(connectPort)) {
        qpcr.disconnect(connectedDevice.getKey());
      }
    }
  }

  @Override
  public AjaxResult connect(String connectPort) {
    try {
      getConnectedDevice(connectPort);
      return AjaxResult.ok(true);
    } catch (DeviceUnregisterException e) {
      return AjaxResult.error(ErrorCode.DEVICE_UNREGISTER);
    } catch (DeviceConnectException e) {
      return AjaxResult.error(ErrorCode.DEVICE_CONNECT_FAIL);
    } catch (DeviceNotFoundException e) {
      return AjaxResult.error(ErrorCode.DEVICE_NOT_FOUND);
    }
  }

  @Override
  public AjaxResult start(Data data) {
    DeviceInfoAdapter deviceInfo;

    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(data.getConnectPort());
    } catch (DeviceUnregisterException e) {
      return AjaxResult.error(ErrorCode.DEVICE_UNREGISTER);
    } catch (DeviceConnectException e) {
      return AjaxResult.error(ErrorCode.DEVICE_CONNECT_FAIL);
    } catch (DeviceNotFoundException e) {
      return AjaxResult.error(ErrorCode.DEVICE_NOT_FOUND);
    }
    deviceInfo = connectedDevice.getDeviceInfo();

    if (!data.getForce() && connectedDevice.getStatus().getWorkStatus() == WorkStatus.WORK) {
      return AjaxResult.ok(WorkStatus.WORK);
    }

    // stepNum 是 Hold, Amplification, Melt, goto (每一个 Amplification 有一个 goto) 的总数, goto 也算一个 step
    short stepNum = 0;
    // protocolDataList 里面放的是 Hold + (Amplification + 0) + Melt 的总数就是有几个 stage, 不用算 goto, 但是 goto 算一个step
    List<Protocol.Stage> protocolDataList = data.getProtocol().getStages();
    if (protocolDataList.size() == 0) {
      return AjaxResult.error(ErrorCode.REQUEST_PARAM_ERROR, "ProtocolData 长度为 0");
    }

    // 判断stepNum的数量,Amplification多加一个goto的step,等于stepNum
    for (Protocol.Stage stage : protocolDataList) {
      switch (stage.getState()) {
        case Protocol.Stage.MELT:
          break;
        case Protocol.Stage.AMPLIFICATION:
          stepNum++;
        default:
          stepNum += stage.getSteps().size();
          break;
      }
    }

    ProgramBean program = new ProgramBean(stepNum);

    // 设置 workspace
    byte[] workspace = program.getWorkspace();
    byte[] wBt = data.getUserName().getBytes();
    System.arraycopy(wBt, 0, workspace, 0, wBt.length);
    program.setWorkspace(workspace);    // 此句十分有必要，此指针非彼指针

    // 设置 programName
    byte[] programName = program.getProgramName();
    byte[] pnBt = data.getProtocol().getName().getBytes();
    System.arraycopy(pnBt, 0, programName, 0, pnBt.length);
    program.setProgramName(programName);    // 此句十分有必要，此指针非彼指针

    // 设置 channels
    byte[] channels = program.getChannels();
    byte[] cBt = data.getProtocol().getChannels();
    System.arraycopy(cBt, 0, channels, 0, cBt.length);
    program.setChannels(channels);  // 此句十分有必要，此指针非彼指针

    // 设置 positions
    byte[] positions = program.getPositions();
    byte[] pBt = data.getProtocol().getPositions();
    System.arraycopy(pBt, 0, positions, 0, pBt.length);
    program.setPositions(positions);    // 此句十分有必要，此指针非彼指针

    program.setHotLidMode((short) (data.getHotLidMode() ? 1 : 0));
    program.setHotLidTemp((short) (data.getCoverTemp() * 100));
    program.setHotLidCloseTemp((short) (data.getLidCloseTemp() * 100));
    program.setExperimentMode((short) (data.getRunModeIsSample() ? 1 : 0));
    program.setSampleVol(data.getReactionVolume()); // 设置 Sample 容量

    // 设置 Melt
    for (Protocol.Stage stage : protocolDataList) {
      if (stage.getState().equals(Protocol.Stage.MELT)) {
        program.setMeltingCurveMode(stage.getHrMeltingCurveMode()
            ? MeltingCurveMode.HR_MELTING_CURVE
            : MeltingCurveMode.MELTING_CURVE);
        Protocol.Stage.Step step1 = stage.getSteps().get(0);
        Protocol.Stage.Step step2 = stage.getSteps().get(1);
        program.setMeltingCurveStartTemp((short) (step1.getTemperature() * 100));
        program.setMeltingCurveEndTemp((short) ((step2.getTemperature() - step1.getGradient()) * 100));
        program.setMeltingCurveStepResolution(Math.abs(step1.getGradient()));
        break;
      }
    }

    ProgramStepBean[] stepBeans = program.getSteps();
    short tempStepIndex = 0;
    for (Protocol.Stage stage : protocolDataList) {
      short firstStepIndex = tempStepIndex;
      switch (stage.getState()) {
        case Protocol.Stage.PRE_READ:
        case Protocol.Stage.POST_READ:
        case Protocol.Stage.HOLD:
        case Protocol.Stage.AMPLIFICATION:
        case Protocol.Stage.INFINITE_HOLD:
          for (Protocol.Stage.Step step : stage.getSteps()) {
            ProgramStepBean programStep;

            Protocol.Stage.Step.AutoDelta autoDelta = step.getAutoDelta();
            Protocol.Stage.Step.Gradient gradient = step.getGradientDeltaTemperature();
            if (gradient.getChecked()) {
              programStep = new ProgramStepBean(ProgramStepName.GRADIENT_TEMP);
              programStep.enableGragient();
              // 设置温度
              short[] temperature = programStep.getTemperature();
              float left = gradient.getStart();
              float right = gradient.getEnd();
              temperature[0] = (short) (left * 100);
              temperature[1] = (short) ((left + right) * 50);
              temperature[2] = (short) (right * 100);
              programStep.setTemperature(temperature);    // 此句十分有必要，此指针非彼指针
            } else {
              programStep = new ProgramStepBean(ProgramStepName.CONSTANT_TEMP);
              programStep.enableTemperature();
              // 设置温度
              short[] temperature = programStep.getTemperature();
              short t = (short) (step.getTemperature() * 100);
              temperature[0] = t;
              temperature[1] = t;
              temperature[2] = t;
              programStep.setTemperature(temperature);    // 此句十分有必要，此指针非彼指针

              // 设置 Ramp Rate
              if (autoDelta.getCheckRampRate()) {
                programStep.enablePidSpeed();
                programStep.setRampRate((short) (autoDelta.getRampRate() * 100));
              }
              // 设置 Auto Delta Temperature
              if (autoDelta.getCheckAutoDeltaTemperature()) {
                programStep.enableDTemperature();
                programStep.setDeltaTemperature((short) (autoDelta.getAutoDeltaTemperature() * 100));
              }
            }

            // 设置时间(这个时间结束后才能获取到数据)
            programStep.setHoldTime(step.getTime());

            // 设置是否采集数据
            programStep.setCollectedMode((short) (step.getRecord() ? 1 : 0));

            // 设置是否自动暂停
            if (autoDelta.getCheckAutoPauseBefore() || autoDelta.getCheckAutoPauseAfter()) {
              programStep.enablePause();
              if (autoDelta.getCheckAutoPauseBefore()) {
                programStep.setPauseBefore((short) 1);
              }
              if (autoDelta.getCheckAutoPauseAfter()) {
                programStep.setPauseAfter((short) 1);
              }
            }
            // 设置 Auto Delta Time
            if (autoDelta.getCheckAutoDeltaTime()) {
              programStep.enableDtime();
              programStep.setDeltaTime(autoDelta.getAutoDeltaTime());
            }
            if (tempStepIndex >= 30) {
              break;
            }
            stepBeans[tempStepIndex++] = programStep;
          }
          break;
      }
      switch (stage.getState()) {
        case Protocol.Stage.AMPLIFICATION:
          ProgramStepBean programStep = new ProgramStepBean(ProgramStepName.GOTO);
          programStep.enableGoTo();
          programStep.setToStep(++firstStepIndex);
          short cycle = stage.getCycle();
          programStep.setGotoTimes(--cycle);
          if (tempStepIndex >= 30) {
            break;
          }
          stepBeans[tempStepIndex++] = programStep;
          break;
        case Protocol.Stage.INFINITE_HOLD:
          stepBeans[tempStepIndex].enableIsForever();
          stepBeans[tempStepIndex].setForever((short) 1);
          break;
      }
    }
    program.setSteps(stepBeans);

    if (!qpcr.setExperimentDataFileName(
        deviceInfo, data.getUserName(), data.getProtocol().getName(), data.getExperimentName())) {
      return AjaxResult.error(ErrorCode.SET_EXPERIMENT_DATA_FILE_NAME_ERROR);
    }
    if (!qpcr.downloadProgram(deviceInfo, program)) {
      return AjaxResult.error(ErrorCode.DOWNLOAD_PROGRAM_ERROR);
    }
    return qpcr.runProgram(deviceInfo) ? AjaxResult.ok(true) : AjaxResult.error(ErrorCode.RUN_PROGRAM_ERROR);
  }

  @Override
  public AjaxResult stop(OperationInfo info) {
    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(info.getConnectPort());
    } catch (DeviceUnregisterException e) {
      return AjaxResult.error(ErrorCode.DEVICE_UNREGISTER);
    } catch (DeviceConnectException e) {
      return AjaxResult.error(ErrorCode.DEVICE_CONNECT_FAIL);
    } catch (DeviceNotFoundException e) {
      return AjaxResult.error(ErrorCode.DEVICE_NOT_FOUND);
    }
    switch (connectedDevice.getStatus().getWorkStatus()) {
      case WorkStatus.NOT_WORK:
        return AjaxResult.ok(true);
      case WorkStatus.WORK:
        if (!info.getForce()) {   // 是否强制执行
          return AjaxResult.error(ErrorCode.DEVICE_WORKING, "仪器正在工作中");
        }
        if (!qpcr.stopProgram(connectedDevice.getDeviceInfo())) {
          return AjaxResult.error(ErrorCode.FAIL, "停止失败");
        }
        return AjaxResult.ok(true);
      case WorkStatus.PAUSE:
        if (!info.getForce()) {
          return AjaxResult.error(ErrorCode.DEVICE_PAUSING, "仪器处于暂停状态");
        }
        if (!qpcr.stopProgram(connectedDevice.getDeviceInfo())) {
          return AjaxResult.error(ErrorCode.FAIL, "停止失败");
        }
        return AjaxResult.ok(true);
      default:
        return AjaxResult.error(ErrorCode.UNKNOWN, "未知错误");
    }
  }

  @Override
  public AjaxResult pause(OperationInfo info) {
    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(info.getConnectPort());
    } catch (DeviceUnregisterException e) {
      return AjaxResult.error(ErrorCode.DEVICE_UNREGISTER);
    } catch (DeviceConnectException e) {
      return AjaxResult.error(ErrorCode.DEVICE_CONNECT_FAIL);
    } catch (DeviceNotFoundException e) {
      return AjaxResult.error(ErrorCode.DEVICE_NOT_FOUND);
    }
    switch (connectedDevice.getStatus().getWorkStatus()) {
      case WorkStatus.PAUSE:
        return AjaxResult.ok(true);
      case WorkStatus.WORK:
        if (!info.getForce()) {
          return AjaxResult.error(ErrorCode.DEVICE_WORKING, "仪器正在工作中");
        }
        if (!qpcr.pauseProgram(connectedDevice.getDeviceInfo())) {
          return AjaxResult.error(ErrorCode.FAIL, "暂停失败");
        }
        return AjaxResult.ok(true);
      case WorkStatus.NOT_WORK:
        return AjaxResult.error(ErrorCode.DEVICE_NOT_WORK, "仪器没有工作");
      default:
        return AjaxResult.error(ErrorCode.UNKNOWN, "未知错误");
    }
  }

  @Override
  public AjaxResult restart(OperationInfo info) {
    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(info.getConnectPort());
    } catch (DeviceUnregisterException e) {
      return AjaxResult.error(ErrorCode.DEVICE_UNREGISTER);
    } catch (DeviceConnectException e) {
      return AjaxResult.error(ErrorCode.DEVICE_CONNECT_FAIL);
    } catch (DeviceNotFoundException e) {
      return AjaxResult.error(ErrorCode.DEVICE_NOT_FOUND);
    }
    switch (connectedDevice.getStatus().getWorkStatus()) {
      case WorkStatus.WORK:
        return AjaxResult.ok(true);
      case WorkStatus.PAUSE:
        if (!info.getForce()) {
          return AjaxResult.error(ErrorCode.DEVICE_PAUSING, "仪器处于暂停状态");
        }
        if (!qpcr.resumeProgram(connectedDevice.getDeviceInfo())) {
          return AjaxResult.error(ErrorCode.FAIL, "恢复启动失败");
        }
        return AjaxResult.ok(true);
      case WorkStatus.NOT_WORK:
        return AjaxResult.error(ErrorCode.DEVICE_NOT_WORK, "仪器没有工作");
      default:
        return AjaxResult.error(ErrorCode.UNKNOWN, "未知错误");
    }
  }

  @Override
  public AjaxResult controlTray(Data data) {
    DeviceInfoAdapter deviceInfo;
    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(data.getConnectPort());
    } catch (DeviceUnregisterException e) {
      return AjaxResult.error(ErrorCode.DEVICE_UNREGISTER);
    } catch (DeviceConnectException e) {
      return AjaxResult.error(ErrorCode.DEVICE_CONNECT_FAIL);
    } catch (DeviceNotFoundException e) {
      return AjaxResult.error(ErrorCode.DEVICE_NOT_FOUND);
    }
    deviceInfo = connectedDevice.getDeviceInfo();
//    return qpcr.controlTray(deviceInfo,data.getControlTray()) ? AjaxResult.ok(true) : AjaxResult.error(ErrorCode.RUN_PROGRAM_ERROR);
    return AjaxResult.ok(true);
  }

  private ConnectedDeviceAdapter getConnectedDevice(String connectPort) throws DeviceUnregisterException, DeviceNotFoundException, DeviceConnectException {
    // 从已连接设备中查找是否已经存在
    ConnectedDeviceDictionary[] connectedDevices = qpcr.getConnectedDevices();
    for (int i = connectedDevices.length - 1; i >= 0; i--) {
      ConnectedDeviceDictionary connectedDeviceDictionary = connectedDevices[i];
      final DeviceInfoAdapter deviceInfo = connectedDeviceDictionary.getKey();
      if (!deviceInfo.getConnectPort().equals(connectPort)) {
        continue;
      }
      if (!access.deviceAccess(deviceInfo.getId())) {
        throw new DeviceUnregisterException(deviceInfo.getId(), "throw exception in iterator of 'Connected Devices' array");
      }
      ConnectedDeviceAdapter connectedDevice = connectedDeviceDictionary.getValue();
      if (!connectedDevice.isAlive()) {
        qpcr.disconnect(deviceInfo);
        continue;
      }
      return connectedDevice;
    }

    // 在已连接设备中查找，发现不存在，则在全部设备中查找是否存在，并连接，然后执行停止方法并返回
    for (int i = connections.length - 1; i >= 0; i--) {
      DeviceInfoAdapter deviceInfo = connections[i];
      if (!deviceInfo.getConnectPort().equals(connectPort)) {
        continue;
      }
      if (!access.deviceAccess(deviceInfo.getId())) {
        throw new DeviceUnregisterException(deviceInfo.getId(), "throw exception in iterator of 'Device Info Adapter(connections)' array which is searched long time ago");
      }
      if (!qpcr.connect(deviceInfo)) {
        break;  // 连接设备失败
      }
      return new ConnectedDeviceAdapter(deviceInfo);
    }

    // 在全部设备中查找不到，则重新搜索
    connections = qpcr.connections();
    for (int i = connections.length - 1; i >= 0; i--) {
      DeviceInfoAdapter deviceInfo = connections[i];
      if (!deviceInfo.getConnectPort().equals(connectPort)) {
        continue;
      }
      if (!access.deviceAccess(deviceInfo.getId())) {
        throw new DeviceUnregisterException(deviceInfo.getId(), "throw exception in iterator of 'Device Info Adapter(connections)' array which searched just now");
      }
      if (!qpcr.connect(deviceInfo)) {
        // 连接设备失败
        throw new DeviceConnectException(deviceInfo.getId(), "throw exception in iterator of 'Device Info Adapter(connections)' array which searched just now");
      }
      return new ConnectedDeviceAdapter(deviceInfo);
    }
    // 找不到已连接设备
    throw new DeviceNotFoundException(connectPort, "can not find device using connect port");
  }

  @Override
  public short refreshData(String ip) {
    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(ip);
    } catch (DeviceUnregisterException | DeviceConnectException | DeviceNotFoundException e) {
      return ConstantUtils.DeviceCode.FAIL;
    }
    qpcr.disconnect(connectedDevice.getDeviceInfo());
    try {
      getConnectedDevice(ip);
    } catch (DeviceUnregisterException | DeviceConnectException | DeviceNotFoundException e) {
      return ConstantUtils.DeviceCode.FAIL;
    }
    return ConstantUtils.DeviceCode.SUCCESS;
  }

  @Override
  public StatusBean getStatus(String ip) {
    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(ip);
    } catch (DeviceUnregisterException | DeviceConnectException | DeviceNotFoundException e) {
      return null;
    }

    return connectedDevice.getStatus();
  }

  @Override
  public QuantificationData getPCRData(String ip) {
    QuantificationData result = new QuantificationData();

    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(ip);
    } catch (DeviceUnregisterException | DeviceConnectException | DeviceNotFoundException e) {
      return result;
    }

    // 接收数据
    final ReceivedNormalDataBean[] receivedNormalDataList = connectedDevice.getAllReceivedRunningExperimentalData();
    if (receivedNormalDataList.length == 0) {
      return result;
    }

    Set<Short> cycleSet = new HashSet<>();
    Set<Short> channelSet = new HashSet<>();
    Set<Short> stepNumberSet = new HashSet<>();
    List<PcrData> pcrDataList = new ArrayList<>();
    for (ReceivedNormalDataBean receivedNormalData : receivedNormalDataList) {
      short cycle = receivedNormalData.getCycle();
      cycleSet.add(cycle);
      short channel = receivedNormalData.getChannel();
      channelSet.add(channel);
      short stepNumber = receivedNormalData.getStepNumber();
      stepNumberSet.add(stepNumber);

      float[] pcrDataArray = PcrData.getInstance(pcrDataList, cycle, channel, stepNumber).getData();
      float[] data = receivedNormalData.getData();
      System.arraycopy(data, 0, pcrDataArray, (receivedNormalData.getPosition() - 1) * data.length, data.length);
    }
    List<Short> cycleList = new ArrayList<>(cycleSet);
    List<Short> channelList = new ArrayList<>(channelSet);
    List<Short> stepNumberList = new ArrayList<>(stepNumberSet);
    Collections.sort(cycleList);
    Collections.sort(channelList);
    Collections.sort(stepNumberList);
    for (Short stepNumber : stepNumberList) {
      for (Short channel : channelList) { // channel 是 1-based
        List<List<Float>> lists = result.getChannel(channel - 1);
        for (Short cycle : cycleList) {
          float[] data = PcrData.getInstance(pcrDataList, cycle, channel, stepNumber).getData();
          for (int i = 0; i < PcrData.POSITION_NUMBER; i++) {
            List<Float> dataList = lists.get(i);
            // 如果要使采集数据 * 1000 作为保存下来的原始数据，在这里处理。
            // 这里没有 * 1000 是因为要使用采集到的原始数据计算 cq 等。
            // 在前端绘制数据时再 * 1000。
            dataList.add(data[i]);
          }
        }
      }
    }

    return result;
  }

  @Override
  public List<List<Float>> getMeltData(String ip) {
    ConnectedDeviceAdapter connectedDevice;
    try {
      connectedDevice = getConnectedDevice(ip);
    } catch (DeviceUnregisterException | DeviceConnectException | DeviceNotFoundException e) {
      return new ArrayList<>();
    }

    ReceivedMeltingDataBean[] src = connectedDevice.getAllReceivedRunningMeltingData();
    List<List<Float>> result = new ArrayList<>();
    // 采集的数据次数
    if (src.length != 0) {
      // 从第一次采集出来的数据中，根据孔位生成 List
      for (int i = 0; i < src[0].getData().length; i++) {
        result.add(new ArrayList<>());
      }
      for (ReceivedMeltingDataBean data : src) {
        float[] d = data.getData();
        for (int j = 0; j < d.length; j++) {
          result.get(j).add(d[j]);   // 如果要使采集数据 * 1000 作为保存下来的原始数据，在这里处理
        }
      }
    }
    return result;
  }
}
